package com.bruce.ai.alibaba.agentcard.discovery.auth;

import com.bruce.ai.alibaba.agentcard.discovery.config.A2AClientConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * 认证服务
 * 统一管理所有认证方式，包括JWT、OAuth2、API密钥等
 * 
 * 特性：
 * - 多种认证方式支持
 * - 认证结果缓存
 * - 统一的认证接口
 * - 认证失败处理
 */
@Service
public class AuthenticationService {
    
    private static final Logger logger = LoggerFactory.getLogger(AuthenticationService.class);
    
    private final JwtTokenValidator jwtTokenValidator;
    private final OAuth2TokenManager oauth2TokenManager;
    private final ApiKeyManager apiKeyManager;
    
    @Autowired
    public AuthenticationService(JwtTokenValidator jwtTokenValidator,
                               OAuth2TokenManager oauth2TokenManager,
                               ApiKeyManager apiKeyManager) {
        this.jwtTokenValidator = jwtTokenValidator;
        this.oauth2TokenManager = oauth2TokenManager;
        this.apiKeyManager = apiKeyManager;
    }
    
    /**
     * 验证认证信息
     * @param authType 认证类型
     * @param credentials 认证凭据
     * @return 认证结果
     */
    public AuthenticationResult authenticate(A2AClientConfig.AuthType authType, Map<String, String> credentials) {
        try {
            switch (authType) {
                case BEARER:
                    return authenticateBearer(credentials.get("token"));
                    
                case API_KEY:
                    return authenticateApiKey(credentials.get("apiKey"));
                    
                case OAUTH2:
                    return authenticateOAuth2(credentials);
                    
                case NONE:
                    return AuthenticationResult.success("No authentication required");
                    
                default:
                    return AuthenticationResult.failure("Unsupported authentication type: " + authType);
            }
        } catch (Exception e) {
            logger.error("Authentication error for type: {}", authType, e);
            return AuthenticationResult.failure("Authentication error: " + e.getMessage());
        }
    }
    
    /**
     * 获取认证头信息
     * @param authType 认证类型
     * @param credentials 认证凭据
     * @return 认证头信息
     */
    public Map<String, String> getAuthHeaders(A2AClientConfig.AuthType authType, Map<String, String> credentials) {
        Map<String, String> headers = new HashMap<>();
        
        switch (authType) {
            case BEARER:
                String bearerToken = credentials.get("token");
                if (bearerToken != null) {
                    headers.put("Authorization", "Bearer " + bearerToken);
                }
                break;
                
            case API_KEY:
                String apiKey = credentials.get("apiKey");
                String headerName = credentials.getOrDefault("headerName", "X-API-Key");
                if (apiKey != null) {
                    headers.put(headerName, apiKey);
                }
                break;
                
            case OAUTH2:
                String oauth2Token = credentials.get("accessToken");
                if (oauth2Token != null) {
                    headers.put("Authorization", "Bearer " + oauth2Token);
                }
                break;
                
            case NONE:
            default:
                // 无需认证头
                break;
        }
        
        return headers;
    }
    
    /**
     * 刷新认证令牌
     * @param authType 认证类型
     * @param credentials 认证凭据
     * @return 新的认证令牌
     */
    public Optional<String> refreshToken(A2AClientConfig.AuthType authType, Map<String, String> credentials) {
        try {
            switch (authType) {
                case OAUTH2:
                    return refreshOAuth2Token(credentials);
                    
                case BEARER:
                case API_KEY:
                    // 这些类型通常不支持刷新，需要重新获取
                    logger.debug("Token refresh not supported for auth type: {}", authType);
                    return Optional.empty();
                    
                default:
                    return Optional.empty();
            }
        } catch (Exception e) {
            logger.error("Token refresh error for type: {}", authType, e);
            return Optional.empty();
        }
    }
    
    /**
     * 检查认证是否即将过期
     * @param authType 认证类型
     * @param credentials 认证凭据
     * @param thresholdSeconds 阈值秒数
     * @return 是否即将过期
     */
    public boolean isAuthExpiringSoon(A2AClientConfig.AuthType authType, Map<String, String> credentials, long thresholdSeconds) {
        switch (authType) {
            case BEARER:
            case API_KEY:
            case OAUTH2:
                // 这些类型的过期检查需要额外的实现
                return false;
                
            default:
                return false;
        }
    }
    
    /**
     * Bearer令牌认证
     */
    private AuthenticationResult authenticateBearer(String token) {
        if (token == null || token.trim().isEmpty()) {
            return AuthenticationResult.failure("Bearer token is required");
        }
        
        // 简单的Bearer令牌验证（实际应用中可能需要更复杂的验证）
        if (token.length() < 10) {
            return AuthenticationResult.failure("Invalid bearer token format");
        }
        
        return AuthenticationResult.success("Bearer token validated");
    }
    
    /**
     * JWT令牌认证
     */
    private AuthenticationResult authenticateJwt(String token) {
        if (token == null || token.trim().isEmpty()) {
            return AuthenticationResult.failure("JWT token is required");
        }
        
        JwtTokenValidator.TokenValidationResult result = jwtTokenValidator.validateToken(token);
        
        if (result.isValid()) {
            String subject = jwtTokenValidator.extractSubject(token).orElse("unknown");
            return AuthenticationResult.success("JWT token validated for subject: " + subject);
        } else if (result.isExpired()) {
            return AuthenticationResult.failure("JWT token has expired");
        } else {
            return AuthenticationResult.failure("Invalid JWT token: " + result.getErrorMessage());
        }
    }
    
    /**
     * API密钥认证
     */
    private AuthenticationResult authenticateApiKey(String apiKey) {
        if (apiKey == null || apiKey.trim().isEmpty()) {
            return AuthenticationResult.failure("API key is required");
        }
        
        ApiKeyManager.ApiKeyValidationResult result = apiKeyManager.validateApiKey(apiKey);
        
        if (result.isValid()) {
            String clientId = result.getKeyInfo().getClientId();
            return AuthenticationResult.success("API key validated for client: " + clientId);
        } else if (result.isExpired()) {
            return AuthenticationResult.failure("API key has expired");
        } else {
            return AuthenticationResult.failure("Invalid API key: " + result.getErrorMessage());
        }
    }
    
    /**
     * OAuth2认证
     */
    private AuthenticationResult authenticateOAuth2(Map<String, String> credentials) {
        String accessToken = credentials.get("accessToken");
        if (accessToken == null || accessToken.trim().isEmpty()) {
            return AuthenticationResult.failure("OAuth2 access token is required");
        }
        
        // 这里可以添加OAuth2令牌的验证逻辑
        // 例如调用OAuth2服务器的introspection端点
        
        return AuthenticationResult.success("OAuth2 token validated");
    }
    
    /**
     * 刷新OAuth2令牌
     */
    private Optional<String> refreshOAuth2Token(Map<String, String> credentials) {
        try {
            String tokenEndpoint = credentials.get("tokenEndpoint");
            String clientId = credentials.get("clientId");
            String clientSecret = credentials.get("clientSecret");
            String refreshToken = credentials.get("refreshToken");
            
            if (tokenEndpoint == null || clientId == null || clientSecret == null || refreshToken == null) {
                logger.warn("Missing required credentials for OAuth2 token refresh");
                return Optional.empty();
            }
            
            String newAccessToken = oauth2TokenManager.refreshAccessToken(tokenEndpoint, clientId, clientSecret, refreshToken);
            return Optional.of(newAccessToken);
            
        } catch (OAuth2TokenManager.OAuth2Exception e) {
            logger.error("Failed to refresh OAuth2 token", e);
            return Optional.empty();
        }
    }
    
    /**
     * 认证结果类
     */
    public static class AuthenticationResult {
        private final boolean success;
        private final String message;
        private final Map<String, Object> attributes;
        
        private AuthenticationResult(boolean success, String message, Map<String, Object> attributes) {
            this.success = success;
            this.message = message;
            this.attributes = attributes != null ? attributes : new HashMap<>();
        }
        
        public static AuthenticationResult success(String message) {
            return new AuthenticationResult(true, message, null);
        }
        
        public static AuthenticationResult success(String message, Map<String, Object> attributes) {
            return new AuthenticationResult(true, message, attributes);
        }
        
        public static AuthenticationResult failure(String message) {
            return new AuthenticationResult(false, message, null);
        }
        
        public boolean isSuccess() {
            return success;
        }
        
        public String getMessage() {
            return message;
        }
        
        public Map<String, Object> getAttributes() {
            return attributes;
        }
        
        public Object getAttribute(String key) {
            return attributes.get(key);
        }
    }
}